package com.doordu.soa.service.web.utils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.doordu.soa.service.comm.ResultCode;
import com.doordu.soa.service.comm.ResultData;
import com.doordu.soa.service.comm.constant.Constant;
import com.doordu.soa.service.comm.realm.FlowUserRealm;
import com.doordu.soa.service.comm.utils.AuthUtils;
import com.doordu.soa.service.comm.vo.PageVo;
import com.doordu.soa.service.web.auth.TokenManager;
import com.doordu.soa.service.web.auth.UserRealm;
import com.doordu.soa.service.web.auth.model.TokenModel;
import com.doordu.soa.service.web.dto.DoorduResult;
import com.doordu.soa.service.web.service.DataValidService;
import com.github.miemiedev.mybatis.paginator.domain.PageList;

public class BaseController {
	private final Logger logger = LoggerFactory.getLogger(BaseController.class);
	@Autowired
	protected TokenManager tokenManager;
	protected String errorMessage = "";

	public ResponseEntity<Object> ResponseJSON(Object body) {
		return ResponseJSON(body, HttpStatus.OK);
	}

	public ResponseEntity<Object> ResponseJSON(Object body, HttpStatus status) {
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		ResponseEntity<Object> res = new ResponseEntity<Object>(body, headers, status);

		// _$_beginTime
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();

		Long beginTime = (Long) request.getAttribute("_$_beginTime");
		if (beginTime != null && beginTime > 0) {
			HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
					.getResponse();

			Long maxTime = (Long) request.getAttribute("_$_use_time_max");

			Long endTime = System.currentTimeMillis();
			Long userTime = endTime - beginTime;
			response.addHeader("time-used", userTime + "ms");

			if (maxTime < userTime) {
				// log warn
			}

		}

		return res;
	}

	/**
	 * 
	 * @Title: result
	 * @Description 正确返回调用此方法
	 * @param t
	 *            DoorduResult 的子类
	 * @return 如果DoorduResult的参数没有指定,则自动赋值为操作成功的值.
	 */
	private <T extends DoorduResult<?>> ResponseEntity<Object> result(T t) {
		DoorduResult<?> r = (DoorduResult<?>) t;

		if (r.getSuccess() == null) {// 没有指定则设置为 true
			r.setSuccess(true);
		}
		return ResponseJSON(t);
	}

	/**
	 * 返回错误结果.
	 * 
	 * @Title: error
	 * @Description
	 * @param t
	 * @return
	 */
	public <T extends DoorduResult<?>> ResponseEntity<Object> error(T t) {
		if (t != null) {
			DoorduResult<?> r = (DoorduResult<?>) t;
			if (r.getSuccess() == null) {
				r.setSuccess(false);
			}
		}

		return ResponseJSON(t);
	}

	/**
	 * 返回正确的响应(200状态码)<br>
	 * <p>
	 * 如果传递的参数为分页对象 {@code PageList}, 则使用分页数据中的总记录数
	 * </p>
	 * <p>
	 * 如果传递的参数为结果对象 {@code DoorduResult}, 则完全使用该对象的属性进行输出.
	 * </p>
	 * <p>
	 * 其他对象则使用默认封装后输出.
	 * </p>
	 * 
	 * @param result
	 *            可以为 null,PageList,DoorduResult 3种对象.其他对象将使用默认输出.
	 * @return 封装好的返回对象 {@code ResponseEntity}
	 */
	public ResponseEntity<Object> ok(Object result) {
		if (result == null) {
			return ok(new Object(), "");
		}
		if (result instanceof PageList) {
			PageList<?> pagelist = (PageList<?>) result;
			Long dc = 0L;

			if (pagelist.getPaginator() != null) {// 没有设置记录数则自动设置
				dc = Long.valueOf(pagelist.getPaginator().getTotalCount());
			}
			return ok(pagelist, dc);
		}
		if (result instanceof DoorduResult) {
			DoorduResult<?> dresult = (DoorduResult<?>) result;
			return result(dresult);
		}
		return ok(result, "");

	}

	/**
	 * 正常接口返回,推荐使用 {@code ok(DoorduResult<?> result) } 方法
	 * 
	 * @see
	 * @param data
	 * @param message
	 * @return
	 */
	public ResponseEntity<Object> ok(Object data, String message) {
		return ok(ResultCode.RESPONSE_SUCCESS, message, "", data, 0L);
	}
	public ResponseEntity<Object> okResponse(Object data, String message,String desc) {
		return ok(ResultCode.RESPONSE_SUCCESS, message, desc, data, 0L);
	}
	/**
	 * 解析ResultData返回结果
	 * 
	 * @param result
	 * @return
	 */
	public ResponseEntity<Object> result(ResultData<?> result) {
		Map<String, Object> resultData = new HashMap<>();

		String msg = null;
		String desc = null;
		String code = null;

		if (result == null) {
			code = ResultCode.RESPONSE_UNKNOWN_ERROR;
			desc = msg = ResultCode.errmap.get(code);
			resultData.put("code", ResultCode.RESPONSE_UNKNOWN_ERROR);
			resultData.put("data", null);
			resultData.put("message", msg);
			resultData.put("desc", desc);
		} else {
			code = result.getCode();
			msg = result.getMsg();
			desc = result.getDesc();
			resultData.put("code", code);
			resultData.put("data", result.getData());
			resultData.put("message", msg);
			resultData.put("desc", desc);
		}

		return ResponseJSON(resultData);
	}

	/**
	 * 正常接口返回,推荐使用 {@code ok(DoorduResult<?> result) } 方法
	 * 
	 * @see
	 * @param data
	 * @param totalCount
	 * @return
	 */
	public ResponseEntity<Object> ok(Object data, Long totalCount) {
		return ok(ResultCode.RESPONSE_SUCCESS, "", "", data, totalCount);
	}

	/**
	 * 正常接口返回,推荐使用
	 * 
	 * @param code
	 * @param msg
	 * @param desc
	 * @param data
	 * @param totalCount
	 * @return
	 */
	public ResponseEntity<Object> ok(String code, String msg, String desc, Object data, Long totalCount) {
		Map<String, Object> resultData = new HashMap<>();
		resultData.put("code", code);
		resultData.put("message", msg);
		resultData.put("data", new Object());// 默认空
		resultData.put("desc", desc);
		if (totalCount != null && totalCount > 0) {
			resultData.put("totalCount", totalCount);
		}
		if (data != null) {
			if (data instanceof PageVo) {
				PageVo pageVo = (PageVo) data;
				if (pageVo != null) {
					resultData.put("data", data == null ? new Object() : pageVo.getContent());
					resultData.put("totalCount", pageVo.getTotalCount());
				}
			} else if (data instanceof PageList) {
				PageList<?> pagelist = (PageList<?>) data;
				if (pagelist.getPaginator() != null) {
					resultData.put("data", data == null ? new Object() : data);
					resultData.put("totalCount", pagelist.getPaginator().getTotalCount());
				}
			} else if (data instanceof List) {
				List<?> list = (List<?>) data;
				if (list != null) {
					resultData.put("data", data == null ? new Object() : data);
					resultData.put("totalCount", list.size());
				}
			} else {
				resultData.put("data", data);
			}
		}
		// TODO Map对象的属性不能自动转换null 为 ""

		return ResponseJSON(resultData);
	}

	/***
	 * 返回业务异常 默认code="400"
	 * 
	 * @param msg
	 * @return
	 */
	public ResponseEntity<Object> error(String msg) {
		return error(ResultCode.RESPONSE_ERROR, msg);
	}

	/***
	 * 
	 * @param msg
	 * @param code
	 * @return
	 */
	public ResponseEntity<Object> error(String code, String msg) {
		return error(code, msg, null);
	}

	/***
	 * @Title: error
	 * @Description:
	 * @author Jason.Rao raoys@doordu.com
	 * @date 2017年4月20日 上午6:38:22
	 * @param code
	 *            错误编码
	 * @param msg
	 *            错误信息
	 * @param desc
	 *            错误描述
	 * @return
	 * @return ResponseEntity<Object>
	 */
	public ResponseEntity<Object> error(String code, String msg, String desc) {
		Map<String, Object> data = new HashMap<>();
		data.put("code", code);
		data.put("message", msg);
		data.put("desc", desc);
		return ResponseJSON(data);
	}

	public ResponseEntity<Object> errorInterface(String code, String msg, String desc, String successFlag) {
		Map<String, Object> data = new HashMap<>();
		data.put("code", code);
		Map<String, String> successMap = new HashMap<>();
		successMap.put("flag", successFlag);
		data.put("data", successMap);
		data.put("message", msg);
		data.put("desc", desc);
		return ResponseJSON(data);
	}

	// public ResponseEntity<Object> defaultError(String desc) {
	// return error(ResultCode.RESPONSE_INTRANET_ERROR,
	// ResultCode.errmap.get(ResultCode.RESPONSE_INTRANET_ERROR),
	// desc);
	// }

	public ResponseEntity<Object> defaultError(Exception ex) {
		Map<String, Object> data = new HashMap<>();
		data.put("code", ResultCode.RESPONSE_INTRANET_ERROR);
		data.put("message", ExceptionUtils.getStackTrace(ex));
		return ResponseJSON(data);
	}

	/**
	 * 校验参数错误
	 * 
	 * @param desc
	 * @return
	 */
	public ResponseEntity<Object> checkParamError(String desc) {
		return error(ResultCode.ERROR_DATA_PARAM, ResultCode.errmap.get(ResultCode.ERROR_DATA_PARAM), desc);
	}

	public ResponseEntity<Object> dataNotMatchError() {
		return error(ResultCode.ERROR_DATA_NOT_MATCH, ResultCode.errmap.get(ResultCode.ERROR_DATA_NOT_MATCH),
				"没有符合要求的数据");
	}

	public ResponseEntity<Object> responseIntranetError() {
		return error(ResultCode.RESPONSE_INTRANET_ERROR, ResultCode.errmap.get(ResultCode.RESPONSE_INTRANET_ERROR),
				null);
	}

	public ResponseEntity<Object> resultDataError(ResultData<?> resultData) {
		return error(resultData.getCode(), StringUtils.isBlank(resultData.getMsg())
				? ResultCode.errmap.get(resultData.getCode()) : resultData.getMsg(), resultData.getDesc());
	}

	public ResponseEntity<Object> resultInterterInfo(ResultData<?> resultData) {
		if (resultData.getMsg().equals("操作成功")) {
			return errorInterface(
					resultData.getCode(), StringUtils.isBlank(resultData.getMsg())
							? ResultCode.errmap.get(resultData.getCode()) : resultData.getMsg(),
					resultData.getDesc(), "1");
		}
		return errorInterface(resultData.getCode(), StringUtils.isBlank(resultData.getMsg())
				? ResultCode.errmap.get(resultData.getCode()) : resultData.getMsg(), resultData.getDesc(), "0");
	}

	public ResponseEntity<Object> checkParamNull(String desc) {
		return error(ResultCode.ERROR_DATA_NULL, ResultCode.errmap.get(ResultCode.ERROR_DATA_NULL), desc);
	}

	public ResponseEntity<Object> hasNoPermission(String desc) {
		return error(ResultCode.ERROR_NOAUTH, ResultCode.errmap.get(ResultCode.ERROR_NOAUTH), desc);
	}

	/***
	 * 获取当前的请求信息.
	 * 
	 * @return
	 */
	public HttpServletRequest getRequest() {
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();

		return request;
	}

	/**
	 * 获取当前登录的用户信息
	 * 
	 * @return
	 */
	public Optional<UserRealm> getUserRealm() {
		HttpServletRequest request = getRequest();
		HttpSession session = request.getSession(false);
		if (session != null) {
			UserRealm realm = (UserRealm) session.getAttribute(UserRealm.USER_REALM_KEY);
			return Optional.ofNullable(realm);
		}
		return Optional.empty();
	}

	/**
	 * 校验数据的合法性
	 * 
	 * @param object
	 * @return
	 */
	public String checkData(Object object) {
		String result = null;
		try {
			DataValidService.valid(object);
		} catch (Exception e) {
			result = "参数校验失败：" + e.getMessage();
		}
		return result;
	}

	/**
	 * 校验分页参数的合法性
	 * 
	 * @param pageParam
	 * @return
	 */
	public String checkPageParam(PageParam pageParam) {
		String result = this.checkData(pageParam);
		if (result == null) {
			if (Integer.valueOf(pageParam.getPage()) <= 0) {
				result = "页码不能小于1";
			}
			if (Integer.valueOf(pageParam.getLimit()) <= 0) {
				result = "每页记录数不能小于1";
			}
		}

		return result;
	}

	protected String getErrorMessage(String errorMessage) {
		if (errorMessage.length() > 50) {
			return "系统内部异常。";
		}
		return errorMessage;
	}

	public FlowUserRealm getCurrentUser(String sessionId) {
		FlowUserRealm flowUserRealm = AuthUtils.getFlowCurrentUser(sessionId);
		return flowUserRealm;
	}

	public FlowUserRealm getCurrentUser(HttpServletRequest request) {
		String sessionId = request.getParameter(Constant.SESSION_ID);
		if (StringUtils.isBlank(sessionId)) {
			return null;
		}
		FlowUserRealm flowUserRealm = AuthUtils.getFlowCurrentUser(sessionId);

		return flowUserRealm;
	}

	protected String getSessionId(HttpServletRequest request) {
		return request.getParameter(Constant.SESSION_ID);
	}


	protected Integer getCompanyId(HttpServletRequest request) {
		TokenModel tokenModel=tokenManager.getTokenModelByToken(request.getParameter("accessToken"));
		if(null==tokenModel){
			return 4;
		}
		return tokenModel.getCompanyId();
	}
}
